//! 第四章：无向图算法
use std::{collections::HashSet, fs};
pub mod breadth_first_search;
pub mod connect;
pub mod cycle;
pub mod depth_first_search;
pub mod edge_weighted;
pub mod symbol_graph;
pub trait Search {
    fn marked(&self, v: usize) -> bool;
    fn count(&self) -> usize;
}
pub trait Path {
    fn has_path_to(&self, v: usize) -> bool;
    fn path_to(&self, v: usize) -> Option<Box<dyn Iterator<Item = usize>>>;
}
pub struct Graph {
    vertex_count: usize,
    edge_count: usize,
    adj: Vec<HashSet<usize>>,
}
impl Graph {
    pub fn new(vertex_count: usize) -> Self {
        assert!(vertex_count > 0);
        let mut adj = Vec::with_capacity(vertex_count);
        for _ in 0..vertex_count {
            adj.push(HashSet::new());
        }
        Graph {
            vertex_count,
            edge_count: 0,
            adj,
        }
    }
}
/// 向图中添加n条边
///
/// `g`:图
///
/// `x`:v
///
/// `y`:v对应的n个w
#[macro_export]
macro_rules! add_edge {
// $(...),+ 包围起来，就可以匹配一个或多个用逗号隔开的表达式
    ($g:ident,$x:expr, $($y:expr),+) =>(
        (
           $(
             $g.add_edge($x,$y)
            ),+
        )
    );
}
impl Graph {
    pub fn vertex_count(&self) -> usize {
        self.vertex_count
    }
    pub fn edge_count(&self) -> usize {
        self.edge_count
    }
    pub fn add_edge(&mut self, v: usize, w: usize) {
        self.adj[v].insert(w);
        self.adj[w].insert(v);
        self.edge_count += 1;
    }
    pub fn adj(&self, v: usize) -> &HashSet<usize> {
        &self.adj[v]
    }
    /// 打印dot格式的图结构
    pub fn print_dot(&self, path: &str) {
        let mut graph = r#"graph{
            label="graph"
             bgcolor=grey
             shape=circle
             "#
        .to_string();
        for v in 0..self.vertex_count {
            for w in self.adj(v).clone() {
                if w > v {
                    graph.push_str(&format!("{} -- {}\n", v, w));
                }
            }
        }
        graph.push('}');
        let _ = fs::write(path, graph);
    }
}
